/*
 *   首先，使用 reactiveMap 的 WeakMap 对象来缓存已经代理过的对象，以避免重复代理。在每次调用 reactive函数时，会先检查目标对象是否已经被代理过，如果是，则直接返回代理后的对象。
 *   接下来，通过 new Proxy 创建了一个代理对象 proxy，并在 get 处理程序中实现了依赖收集的逻辑。当访问代理对象的属性时，会返回对应属性的值，并且在获取 IS_REACTIVE 属性时返回 true。这样，我们可以通过访问 state1.IS_REACTIVE 来检查一个对象是否为响应式对象。
 *   在 set 处理程序中，通过调用 Reflect.set 来设置目标对象的属性值，并返回结果。
 *   最后，将代理对象存储在 reactiveMap 中，以便下次调用 reactive 函数时可以直接返回已经代理过的对象。
 *   综上所述，给定的代码实现了一个简单的响应式函数 reactive，它能够将对象转换为响应式对象并返回代理后的对象。同时，通过缓存已代理的对象，确保多次调用 reactive 函数返回的对象是相同的。
 */
const state = {
  data: "课程视频",
  filedata: "课程文件",
};

// 标识对象是否被代理过

const ReactiveFlags = {
  IS_REACTIVE: "__v_isReactive",
};

// 判断是否为对象
const isObject = (obj) => {
  return typeof obj == "object" && obj !== null;
};

// TODO：待补充代码
const reactiveMap = new WeakMap(); // 缓存列表

const reactive = (target) => {
  if (!isObject(target)) return target;

  // TODO：待补充代码
  if (target[ReactiveFlags.IS_REACTIVE]) {
    // 在创建响应式对象时先进行取值，看是否已经是响应式对象
    return target;
  }
  const exisitingProxy = reactiveMap.get(target); // 如果已经代理过则直接返回代理后的对象
  if (exisitingProxy) {
    return exisitingProxy;
  }
  const proxy = new Proxy(
    target,
    (mutableHandlers = {
      get(target, key, receiver) {
        if (key === ReactiveFlags.IS_REACTIVE) {
          // 在get中增加标识，当获取 IS_REACTIVE 时返回true
          return true;
        }
        // 当获取值时进行依赖收集
        const res = Reflect.get(target, key, receiver);
        return res;
      },
      set(target, key, value, receiver) {
        // 当赋值时重新触发执行效果
        const result = Reflect.set(target, key, value, receiver);
        return result;
      },
    })
  ); // 对对象进行代理
  reactiveMap.set(target, proxy);

  // TODO:待补充代码

  return proxy;
};

const state1 = reactive(state);
const state2 = reactive(state);
const state3 = reactive(state2);

console.log(state1 === state2 && state2 === state3); // 输出 true

// 以下代码为检测需要，请勿删除。
try {
  module.exports = reactive;
} catch (e) {}
